﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SimpleData.ObjectModel.Collections
{
	public class HybridCollection<TKey, TValue> : ICollection<TValue> // Dictionary<TKey, TValue>, ICollection<TValue>
	{
		/// <summary>
		/// 
		/// </summary>
		/// <param name="keyExtractor"></param>
		public HybridCollection( Func<TValue, TKey> keyExtractor )
			: this( keyExtractor, EqualityComparer<TKey>.Default )
		{ }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="keyExtractor"></param>
		/// <param name="comparer"></param>
		public HybridCollection( Func<TValue, TKey> keyExtractor, IEqualityComparer<TKey> comparer )
			//: base( comparer )
		{
			keyExtractor.Throws().IfNull();

			this.KeyExtractor = keyExtractor;
			if ( comparer == null )
				this.InnerDictionary = new Dictionary<TKey, TValue>();
			else
				this.InnerDictionary = new Dictionary<TKey, TValue>( comparer );
		}

		/// <summary>
		/// Obtém ou define a função utilizada para obter a chave do item
		/// </summary>
		public Func<TValue, TKey> KeyExtractor
		{
			get;
			private set;
		}

		/// <summary>
		/// Obtém ou define o dicionário utilizado internamente
		/// </summary>
		protected IDictionary<TKey, TValue> InnerDictionary
		{
			get;
			private set;
		}

		public TValue this[ TKey key ]
		{
			get { return this.InnerDictionary[ key ]; }
			set { this.InnerDictionary[ key ] = value; }
		}

		public bool TryGetValue( TKey key, out TValue value )
		{
			return this.InnerDictionary.TryGetValue( key, out value );
		}

		#region ICollection<TValue> Members

		public void Add( TValue item )
		{
			this.InnerDictionary.Add( this.KeyExtractor( item ), item );
		}

		public bool Contains( TValue item )
		{
			return this.InnerDictionary.Values.Contains( item );
		}

		public void CopyTo( TValue[] array, int arrayIndex )
		{
			this.InnerDictionary.Values.CopyTo( array, arrayIndex );
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public bool Remove( TValue item )
		{
			return this.InnerDictionary.Remove( this.KeyExtractor( item ) );
		}

		#endregion

		#region IEnumerable<TValue> Members

		public IEnumerator<TValue> GetEnumerator()
		{
			return this.InnerDictionary.Values.GetEnumerator();
		}

		#endregion

		#region ICollection<TValue> Members


		public void Clear()
		{
			this.InnerDictionary.Clear();
		}

		public int Count
		{
			get { return this.InnerDictionary.Count; }
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		#endregion
	}
}
